package com.sunday.framework.validation.autoconfiguration;

import com.sunday.common.validation.ParameterValidator;
import com.sunday.redisson.lock.DistributedLock;
import com.sunday.redisson.lock.DistributedLockValidator;
import lombok.extern.slf4j.Slf4j;
import org.aopalliance.intercept.MethodInterceptor;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Arrays;

/**
 * @Description: 参数验证及参数redis绑定
 * <p>
 * 请求参数验证 - 默认实现 :
 * 1. 请求参数合规性验证(javax.validation.Validation)
 * 2. 请求参数分布式锁验证(com.sunday.redisson.lock.DistributedLockValidator)
 */
@Slf4j
@Configuration
@ConditionalOnProperty(prefix = "sunday.framework.validation", value = "execution")
public class ValidationAdvisorAutoConfiguration {

    @Bean
    public Advisor validationPointcutAdvisor(@Value("${sunday.framework.validation.execution}") String execution) {
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression(execution);
        return new DefaultPointcutAdvisor(pointcut, (MethodInterceptor) invocation -> {
            try {
                /** 传参实体 + 分布式锁 参数验证 */
                Arrays.stream(invocation.getArguments())
                        .forEach(param -> {
                            ParameterValidator.validate(param);
                            DistributedLockValidator.annotationLock(param);
                        });
                /** 执行方法 */
                return invocation.proceed();
            } finally {
                DistributedLock.unlock();
            }
        });
    }
}
